package com.xiaohua.api.service.impl;

import com.aliyun.docmind_api20220711.Client;
import com.aliyun.docmind_api20220711.models.*;
import com.aliyun.teautil.models.RuntimeOptions;
import com.xiaohua.api.service.IXhDocumentService;
import com.xiaohua.api.common.properties.AliYunProperties;
import com.xiaohua.common.core.domain.AjaxResult;
import com.xiaohua.common.utils.StringUtils;
import com.xiaohua.api.utils.file.FileTypeUtils;
import com.xiaohua.api.utils.document.DocumentUtils;
import com.xiaohua.common.config.RuoYiConfig;
import com.xiaohua.common.constant.Constants;
import com.xiaohua.framework.config.ServerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import com.xiaohua.api.service.IXhFileService;
import com.xiaohua.api.service.IOperationLogService;
import com.xiaohua.common.utils.SecurityUtils;

/**
 * 文档转换服务实现类
 *
 * @author
 * @date 2025-03-29
 */
@Service
public class XhDocumentServiceImpl implements IXhDocumentService {

    private static final Logger log = LoggerFactory.getLogger(XhDocumentServiceImpl.class);

    @Autowired
    private AliYunProperties aliYunProperties;
    
    @Autowired
    private Client docmindClient;
    
    @Autowired
    private ServerConfig serverConfig;
    
    @Autowired
    private IOperationLogService operationLogService;
    
    @Autowired
    private IXhFileService xhFileService;

    /**
     * 初始化阿里云客户端（已废弃，使用注入的Bean）
     *
     * @return 阿里云文档转换客户端
     * @deprecated 请使用注入的docmindClient Bean
     */
    @Deprecated
    private com.aliyun.docmind_api20220711.Client initClient() throws Exception {
        // 获取AK/SK，并进行空值检查
        String accessKeyId = aliYunProperties.getAccessKeyId();
        String accessKeySecret = aliYunProperties.getAccessKeySecret();
        
        if (accessKeyId == null || accessKeySecret == null) {
            log.error("阿里云API凭证未正确加载，AccessKeyId或AccessKeySecret为空");
            throw new RuntimeException("阿里云API凭证未正确加载，请检查数据库配置");
        }
        
        log.info("初始化阿里云文档转换客户端，使用AK：{}", accessKeyId.substring(0, Math.min(4, accessKeyId.length())) + "********");
        
        try {
            // 创建配置，明确使用最新的客户端初始化方式
            com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
            config.setAccessKeyId(accessKeyId);
            config.setAccessKeySecret(accessKeySecret);
            config.setEndpoint("docmind-api.cn-hangzhou.aliyuncs.com");
            
            // 使用配置创建客户端
            return new com.aliyun.docmind_api20220711.Client(config);
        } catch (Exception e) {
            log.error("初始化阿里云客户端失败：{}", e.getMessage(), e);
            throw new RuntimeException("初始化阿里云客户端失败：" + e.getMessage(), e);
        }
    }

    /**
     * 查询文档转换结果
     *
     * @param taskId 任务ID
     * @return 转换结果
     */
    @Override
    public AjaxResult getDocumentConvertResult(String taskId) throws Exception {
        if (StringUtils.isEmpty(taskId)) {
            return AjaxResult.error("任务ID不能为空");
        }

        // 如果不是以docmind-开头的任务ID，说明不是阿里云任务
        if (!taskId.startsWith("docmind-")) {
            return AjaxResult.error("无效的任务ID，仅支持查询阿里云处理的任务");
        }

        // 使用注入的客户端
        // com.aliyun.docmind_api20220711.Client client = initClient();

        // 构建请求
        GetDocumentConvertResultRequest request = new GetDocumentConvertResultRequest();
        request.id = taskId;

        // 发送请求
        GetDocumentConvertResultResponse response = docmindClient.getDocumentConvertResult(request);
        
        // 处理响应
        if (response.body.completed) {
            if ("Success".equals(response.body.status)) {
                return AjaxResult.success("文档转换成功")
                        .put("taskId", taskId)
                        .put("completed", true)
                        .put("data", response.body.data);
            } else {
                // 转换失败
                return AjaxResult.error(String.format("文档转换失败，错误码：%s，错误信息：%s", 
                        response.body.code, response.body.message))
                        .put("taskId", taskId)
                        .put("completed", true);
            }
        } else {
            // 转换中
            return AjaxResult.success("文档转换进行中")
                    .put("taskId", taskId)
                    .put("completed", false)
                    .put("message", response.body.message);
        }
    }

    /**
     * PDF转Word - 文件上传方式
     *
     * @param file PDF文件
     * @param formulaEnhancement 是否启用公式增强
     * @return 转换结果
     */
    @Override
    public AjaxResult convertPdfToWord(MultipartFile file, Boolean formulaEnhancement) throws Exception {
        if (file == null) {
            return AjaxResult.error("PDF文件不能为空");
        }

        // 校验文件类型
        String originalFilename = file.getOriginalFilename();
        if (!FileTypeUtils.isPdf(originalFilename)) {
            return AjaxResult.error("仅支持PDF格式文件");
        }

        try {
            // 创建运行参数
            RuntimeOptions runtime = new RuntimeOptions();
            
            // 初始化客户端
            com.aliyun.docmind_api20220711.Client client = initClient();

            // 构建请求
            SubmitConvertPdfToWordJobAdvanceRequest request = new SubmitConvertPdfToWordJobAdvanceRequest();
            
            // 使用try-with-resources确保输入流在使用后被关闭
            try (java.io.InputStream inputStream = file.getInputStream()) {
                request.fileUrlObject = inputStream;
                request.fileName = originalFilename;
                
                // 设置公式增强识别
                if (formulaEnhancement != null && formulaEnhancement) {
                    // 使用布尔值设置公式增强
                    Map<String, Object> formulaEnhanceMap = new HashMap<>();
                    formulaEnhanceMap.put("formulaEnhancement", true);
                    // 通过反射设置字段
                    java.lang.reflect.Field field = request.getClass().getDeclaredField("formulaEnhancement");
                    field.setAccessible(true);
                    field.set(request, true);
                }

                // 发送请求
                SubmitConvertPdfToWordJobResponse response = client.submitConvertPdfToWordJobAdvance(request, runtime);
                
                // 返回任务ID
                AjaxResult result = AjaxResult.success("PDF转Word任务提交成功")
                        .put("taskId", response.body.data.id);
                return saveFileAndLog(getUserId(), result, "PDF转Word");
            } // 这里inputStream会自动关闭
        } catch (Exception e) {
            log.error("PDF转Word处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("PDF转Word处理失败：" + e.getMessage());
        }
    }

    /**
     * PDF转Word - Base64编码方式
     */
    @Override
    public AjaxResult convertPdfToWordByBase64(String fileBase64, Boolean formulaEnhancement) throws Exception {
        if (StringUtils.isEmpty(fileBase64)) {
            return AjaxResult.error("PDF文件Base64编码不能为空");
        }

        // 将Base64转换为临时文件
        byte[] fileBytes = Base64.getDecoder().decode(fileBase64);
        File tempFile = File.createTempFile("pdf_to_word_", ".pdf");
        org.apache.commons.io.FileUtils.writeByteArrayToFile(tempFile, fileBytes);

        // 创建运行参数
        RuntimeOptions runtime = new RuntimeOptions();
        
        // 初始化客户端
        com.aliyun.docmind_api20220711.Client client = initClient();

        // 构建请求
        SubmitConvertPdfToWordJobAdvanceRequest request = new SubmitConvertPdfToWordJobAdvanceRequest();
        
        FileInputStream fileInputStream = null;
        try {
            // 使用输入流
            fileInputStream = new FileInputStream(tempFile);
            request.fileUrlObject = fileInputStream;
            request.fileName = "document.pdf";
            
            // 设置公式增强识别
            if (formulaEnhancement != null && formulaEnhancement) {
                // 使用布尔值设置公式增强
                Map<String, Object> formulaEnhanceMap = new HashMap<>();
                formulaEnhanceMap.put("formulaEnhancement", true);
                // 通过反射设置字段
                java.lang.reflect.Field field = request.getClass().getDeclaredField("formulaEnhancement");
                field.setAccessible(true);
                field.set(request, true);
            }

            // 发送请求
            SubmitConvertPdfToWordJobResponse response = client.submitConvertPdfToWordJobAdvance(request, runtime);
            
            // 返回任务ID
            AjaxResult result = AjaxResult.success("PDF转Word任务提交成功")
                    .put("taskId", response.body.data.id);
            return saveFileAndLog(getUserId(), result, "PDF转Word");
        } finally {
            // 关闭输入流
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    log.warn("关闭文件输入流失败: {}", e.getMessage());
                }
            }
            
            // 删除临时文件
            if (tempFile.exists()) {
                if (!tempFile.delete()) {
                    log.warn("删除临时文件失败: {}", tempFile.getAbsolutePath());
                    // 标记为在VM退出时删除
                    tempFile.deleteOnExit();
                }
            }
        }
    }

    /**
     * PDF转Word - URL方式
     */
    @Override
    public AjaxResult convertPdfToWordByUrl(String fileUrl, Boolean formulaEnhancement) throws Exception {
        if (StringUtils.isEmpty(fileUrl)) {
            return AjaxResult.error("PDF文件URL不能为空");
        }

        // 初始化客户端
        com.aliyun.docmind_api20220711.Client client = initClient();

        // 构建请求
        SubmitConvertPdfToWordJobRequest request = new SubmitConvertPdfToWordJobRequest();
        request.fileUrl = fileUrl;
        request.fileName = "document.pdf";
        
        // 设置公式增强识别
        if (formulaEnhancement != null && formulaEnhancement) {
            // 使用布尔值设置公式增强
            Map<String, Object> formulaEnhanceMap = new HashMap<>();
            formulaEnhanceMap.put("formulaEnhancement", true);
            // 通过反射设置字段
            java.lang.reflect.Field field = request.getClass().getDeclaredField("formulaEnhancement");
            field.setAccessible(true);
            field.set(request, true);
        }

        // 发送请求
        SubmitConvertPdfToWordJobResponse response = client.submitConvertPdfToWordJob(request);
        
        // 返回任务ID
        AjaxResult result = AjaxResult.success("PDF转Word任务提交成功")
                .put("taskId", response.body.data.id);
        return saveFileAndLog(getUserId(), result, "PDF转Word");
    }

    /**
     * 图片转Word - 文件上传方式
     */
    @Override
    public AjaxResult convertImageToWord(List<MultipartFile> files, String imageNameExtension) throws Exception {
        if (files == null || files.isEmpty()) {
            return AjaxResult.error("图片文件不能为空");
        }

        if (files.size() > 30) {
            return AjaxResult.error("图片数量超过限制，最多支持30张图片");
        }

        // 校验文件类型
        for (MultipartFile file : files) {
            String originalFilename = file.getOriginalFilename();
            if (!FileTypeUtils.isImage(originalFilename)) {
                return AjaxResult.error("仅支持图片格式文件(jpg/jpeg/png/bmp/gif)");
            }
        }

        // 上传文件到临时URL
        List<String> imageUrls = new ArrayList<>();
        for (MultipartFile file : files) {
            // 实际项目中应该上传到OSS或者其他存储，这里简化处理，假设已获取URL
            // imageUrls.add(uploadToTempUrl(file));
            
            // 实际开发中需要实现文件上传，并获取URL
            // 示例：将文件转为Base64编码处理
            byte[] fileBytes = file.getBytes();
            String base64 = Base64.getEncoder().encodeToString(fileBytes);
            // 使用Base64方式处理
            return convertImageToWordByBase64(Collections.singletonList(base64), imageNameExtension);
        }

        return convertImageToWordByUrl(imageUrls, imageNameExtension);
    }

    /**
     * 图片转Word - Base64编码方式
     */
    @Override
    public AjaxResult convertImageToWordByBase64(List<String> fileBase64List, String imageNameExtension) throws Exception {
        if (fileBase64List == null || fileBase64List.isEmpty()) {
            return AjaxResult.error("图片Base64编码不能为空");
        }

        if (fileBase64List.size() > 30) {
            return AjaxResult.error("图片数量超过限制，最多支持30张图片");
        }

        // 将Base64转换为临时URL
        List<String> imageUrls = new ArrayList<>();
        for (String base64 : fileBase64List) {
            // 实际项目中应该上传到OSS或者其他存储，这里简化处理，假设已获取URL
            // imageUrls.add(uploadBase64ToTempUrl(base64));
            
            // 由于本案例中没有实现实际的上传逻辑，我们只能使用URL方式
            // 这里虚构一个处理步骤
            log.warn("Base64转URL功能尚未实现，请在实际项目中开发此功能");
            return AjaxResult.error("Base64转URL功能尚未实现，请使用文件上传或URL方式");
        }

        return convertImageToWordByUrl(imageUrls, imageNameExtension);
    }

    /**
     * 图片转Word - URL方式
     */
    @Override
    public AjaxResult convertImageToWordByUrl(List<String> imageUrls, String imageNameExtension) throws Exception {
        if (imageUrls == null || imageUrls.isEmpty()) {
            return AjaxResult.error("图片URL不能为空");
        }

        if (imageUrls.size() > 30) {
            return AjaxResult.error("图片数量超过限制，最多支持30张图片");
        }

        // 初始化客户端
        com.aliyun.docmind_api20220711.Client client = initClient();

        // 构建请求
        SubmitConvertImageToWordJobRequest request = new SubmitConvertImageToWordJobRequest();
        request.imageUrls = imageUrls;
        
        // 设置图片格式
        if (StringUtils.isNotEmpty(imageNameExtension)) {
            request.imageNameExtension = imageNameExtension;
        } else {
            // 如果未提供扩展名，默认为jpg
            request.imageNameExtension = "jpg";
        }

        // 发送请求
        SubmitConvertImageToWordJobResponse response = client.submitConvertImageToWordJob(request);
        
        // 返回任务ID
        AjaxResult result = AjaxResult.success("图片转Word任务提交成功")
                .put("taskId", response.body.data.id);
        return saveFileAndLog(getUserId(), result, "图片转Word");
    }

    /**
     * PDF转图片 - 文件上传方式
     *
     * @param file PDF文件
     * @return 转换结果
     */
    @Override
    public AjaxResult convertPdfToImage(MultipartFile file) throws Exception {
        if (file == null) {
            return AjaxResult.error("PDF文件不能为空");
        }

        // 校验文件类型
        String originalFilename = file.getOriginalFilename();
        if (!FileTypeUtils.isPdf(originalFilename)) {
            return AjaxResult.error("仅支持PDF格式文件");
        }

        try {
            log.info("开始PDF转图片处理，文件名：{}", originalFilename);
            
            // 创建运行参数
            RuntimeOptions runtime = new RuntimeOptions();
            
            // 构建请求
            SubmitConvertPdfToImageJobAdvanceRequest request = new SubmitConvertPdfToImageJobAdvanceRequest();
            
            // 使用try-with-resources确保输入流在使用后被关闭
            try (java.io.InputStream inputStream = file.getInputStream()) {
                request.fileUrlObject = inputStream;
                request.fileName = originalFilename != null ? originalFilename : "document.pdf";
                
                // 发送请求
                log.info("发送PDF转图片请求到阿里云");
                SubmitConvertPdfToImageJobResponse response = docmindClient.submitConvertPdfToImageJobAdvance(request, runtime);
                
                // 检查响应
                if (response == null || response.body == null || response.body.data == null) {
                    log.error("PDF转图片响应异常：响应为空");
                    return AjaxResult.error("PDF转图片请求失败：获取到空响应");
                }
                
                String taskId = response.body.data.id;
                log.info("PDF转图片任务提交成功，任务ID：{}", taskId);
                
                // 返回任务ID
                AjaxResult result = AjaxResult.success("PDF转图片任务提交成功")
                        .put("taskId", taskId);
                return saveFileAndLog(getUserId(), result, "PDF转图片");
            } // 这里inputStream会自动关闭
                    
        } catch (RuntimeException e) {
            log.error("PDF转图片处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("PDF转图片处理失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("PDF转图片处理出现未知异常：{}", e.getMessage(), e);
            return AjaxResult.error("PDF转图片处理失败：" + e.getMessage());
        }
    }

    /**
     * PDF转图片 - Base64编码方式
     */
    @Override
    public AjaxResult convertPdfToImageByBase64(String fileBase64) throws Exception {
        if (StringUtils.isEmpty(fileBase64)) {
            return AjaxResult.error("PDF文件Base64编码不能为空");
        }

        // 将Base64转换为临时文件
        byte[] fileBytes = Base64.getDecoder().decode(fileBase64);
        File tempFile = File.createTempFile("pdf_to_image_", ".pdf");
        org.apache.commons.io.FileUtils.writeByteArrayToFile(tempFile, fileBytes);

        // 创建运行参数
        RuntimeOptions runtime = new RuntimeOptions();
        
        // 初始化客户端
        com.aliyun.docmind_api20220711.Client client = initClient();

        // 构建请求
        SubmitConvertPdfToImageJobAdvanceRequest request = new SubmitConvertPdfToImageJobAdvanceRequest();
        
        FileInputStream fileInputStream = null;
        try {
            // 使用try-with-resources确保输入流在使用后被关闭
            fileInputStream = new FileInputStream(tempFile);
            request.fileUrlObject = fileInputStream;
            request.fileName = "document.pdf";

            // 发送请求
            SubmitConvertPdfToImageJobResponse response = client.submitConvertPdfToImageJobAdvance(request, runtime);
            
            // 返回任务ID
            AjaxResult result = AjaxResult.success("PDF转图片任务提交成功")
                    .put("taskId", response.body.data.id);
            return saveFileAndLog(getUserId(), result, "PDF转图片");
        } finally {
            // 关闭输入流
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    log.warn("关闭文件输入流失败: {}", e.getMessage());
                }
            }
            
            // 删除临时文件
            if (tempFile.exists()) {
                if (!tempFile.delete()) {
                    log.warn("删除临时文件失败: {}", tempFile.getAbsolutePath());
                    // 标记为在VM退出时删除
                    tempFile.deleteOnExit();
                }
            }
        }
    }

    /**
     * PDF转图片 - URL方式
     */
    @Override
    public AjaxResult convertPdfToImageByUrl(String fileUrl) throws Exception {
        if (StringUtils.isEmpty(fileUrl)) {
            return AjaxResult.error("PDF文件URL不能为空");
        }

        // 初始化客户端
        com.aliyun.docmind_api20220711.Client client = initClient();

        // 构建请求
        SubmitConvertPdfToImageJobRequest request = new SubmitConvertPdfToImageJobRequest();
        request.fileUrl = fileUrl;
        request.fileName = "document.pdf";

        // 发送请求
        SubmitConvertPdfToImageJobResponse response = client.submitConvertPdfToImageJob(request);
        
        // 返回任务ID
        AjaxResult result = AjaxResult.success("PDF转图片任务提交成功")
                .put("taskId", response.body.data.id);
        return saveFileAndLog(getUserId(), result, "PDF转图片");
    }

    /**
     * 图片转PDF - 文件上传方式
     */
    @Override
    public AjaxResult convertImageToPdf(List<MultipartFile> files, String imageNameExtension) throws Exception {
        if (files == null || files.isEmpty()) {
            return AjaxResult.error("图片文件不能为空");
        }

        if (files.size() > 30) {
            return AjaxResult.error("图片数量超过限制，最多支持30张图片");
        }

        // 校验文件类型
        for (MultipartFile file : files) {
            String originalFilename = file.getOriginalFilename();
            if (!FileTypeUtils.isImage(originalFilename)) {
                return AjaxResult.error("仅支持图片格式文件(jpg/jpeg/png/bmp/gif)");
            }
        }

        // 上传文件到临时URL
        List<String> imageUrls = new ArrayList<>();
        for (MultipartFile file : files) {
            // 实际项目中应该上传到OSS或者其他存储，这里简化处理，假设已获取URL
            // imageUrls.add(uploadToTempUrl(file));
            
            // 实际开发中需要实现文件上传，并获取URL
            // 示例：将文件转为Base64编码处理
            byte[] fileBytes = file.getBytes();
            String base64 = Base64.getEncoder().encodeToString(fileBytes);
            // 使用Base64方式处理
            return convertImageToPdfByBase64(Collections.singletonList(base64), imageNameExtension);
        }

        return convertImageToPdfByUrl(imageUrls, imageNameExtension);
    }

    /**
     * 图片转PDF - Base64编码方式
     */
    @Override
    public AjaxResult convertImageToPdfByBase64(List<String> fileBase64List, String imageNameExtension) throws Exception {
        if (fileBase64List == null || fileBase64List.isEmpty()) {
            return AjaxResult.error("图片Base64编码不能为空");
        }

        if (fileBase64List.size() > 30) {
            return AjaxResult.error("图片数量超过限制，最多支持30张图片");
        }

        // 将Base64转换为临时URL
        List<String> imageUrls = new ArrayList<>();
        for (String base64 : fileBase64List) {
            // 实际项目中应该上传到OSS或者其他存储，这里简化处理，假设已获取URL
            // imageUrls.add(uploadBase64ToTempUrl(base64));
            
            // 由于本案例中没有实现实际的上传逻辑，我们只能使用URL方式
            // 这里虚构一个处理步骤
            log.warn("Base64转URL功能尚未实现，请在实际项目中开发此功能");
            return AjaxResult.error("Base64转URL功能尚未实现，请使用文件上传或URL方式");
        }

        return convertImageToPdfByUrl(imageUrls, imageNameExtension);
    }

    /**
     * 图片转PDF - URL方式
     */
    @Override
    public AjaxResult convertImageToPdfByUrl(List<String> imageUrls, String imageNameExtension) throws Exception {
        if (imageUrls == null || imageUrls.isEmpty()) {
            return AjaxResult.error("图片URL不能为空");
        }

        if (imageUrls.size() > 30) {
            return AjaxResult.error("图片数量超过限制，最多支持30张图片");
        }

        // 初始化客户端
        com.aliyun.docmind_api20220711.Client client = initClient();

        // 构建请求
        SubmitConvertImageToPdfJobRequest request = new SubmitConvertImageToPdfJobRequest();
        request.imageUrls = imageUrls;
        
        // 设置图片格式
        if (StringUtils.isNotEmpty(imageNameExtension)) {
            request.imageNameExtension = imageNameExtension;
        } else {
            // 如果未提供扩展名，默认为jpg
            request.imageNameExtension = "jpg";
        }

        // 发送请求
        SubmitConvertImageToPdfJobResponse response = client.submitConvertImageToPdfJob(request);
        
        // 返回任务ID
        AjaxResult result = AjaxResult.success("图片转PDF任务提交成功")
                .put("taskId", response.body.data.id);
        return saveFileAndLog(getUserId(), result, "图片转PDF");
    }

    /**
     * Word转PDF - 文件上传方式
     *
     * @param file Word文件
     * @return 转换结果
     */
    @Override
    public AjaxResult convertWordToPdf(MultipartFile file) throws Exception {
        if (file == null) {
            return AjaxResult.error("Word文件不能为空");
        }

        // 校验文件类型
        String originalFilename = file.getOriginalFilename();
        if (!FileTypeUtils.isWord(originalFilename)) {
            return AjaxResult.error("仅支持DOC、DOCX格式文件");
        }

        try {
            // 创建临时文件
            File tempWordFile = DocumentUtils.saveTempFile(file, "word_to_pdf_", 
                    originalFilename.substring(originalFilename.lastIndexOf(".")));
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_conversion" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 生成唯一的输出文件名
            String outputFileName = DocumentUtils.generateTempFileName("word_to_pdf_", ".pdf");
            String outputPdfPath = outputDir + File.separator + outputFileName;
            
            // 执行转换
            boolean success = DocumentUtils.convertWordToPdf(tempWordFile, outputPdfPath);
            
            if (success) {
                // 将本地文件路径转换为HTTP URL，包含完整域名
                String httpUrl = DocumentUtils.getHttpUrl(outputPdfPath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                
                // 返回HTTP URL
                AjaxResult result = AjaxResult.success("Word转PDF成功")
                        .put("url", httpUrl);
                return saveFileAndLog(getUserId(), result, "Word转PDF");
            } else {
                return AjaxResult.error("Word转PDF失败");
            }
        } catch (Exception e) {
            log.error("Word转PDF处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("Word转PDF处理失败：" + e.getMessage());
        }
    }

    /**
     * Word转PDF - Base64编码方式
     *
     * @param fileBase64 Word文件的Base64编码
     * @return 转换结果
     */
    @Override
    public AjaxResult convertWordToPdfByBase64(String fileBase64) throws Exception {
        if (StringUtils.isEmpty(fileBase64)) {
            return AjaxResult.error("Word文件Base64编码不能为空");
        }

        try {
            // 将Base64转换为临时文件
            File tempWordFile = DocumentUtils.saveTempFileFromBase64(fileBase64, "word_to_pdf_", ".docx");
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_conversion" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 生成唯一的输出文件名
            String outputFileName = DocumentUtils.generateTempFileName("word_to_pdf_", ".pdf");
            String outputPdfPath = outputDir + File.separator + outputFileName;
            
            // 执行转换
            boolean success = DocumentUtils.convertWordToPdf(tempWordFile, outputPdfPath);
            
            if (success) {
                // 将本地文件路径转换为HTTP URL，包含完整域名
                String httpUrl = DocumentUtils.getHttpUrl(outputPdfPath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                
                // 返回HTTP URL
                AjaxResult result = AjaxResult.success("Word转PDF成功")
                        .put("url", httpUrl);
                return saveFileAndLog(getUserId(), result, "Word转PDF");
            } else {
                return AjaxResult.error("Word转PDF失败");
            }
        } catch (Exception e) {
            log.error("Word转PDF处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("Word转PDF处理失败：" + e.getMessage());
        }
    }

    /**
     * Word转PDF - URL方式
     *
     * @param fileUrl Word文件的URL
     * @return 转换结果
     */
    @Override
    public AjaxResult convertWordToPdfByUrl(String fileUrl) throws Exception {
        if (StringUtils.isEmpty(fileUrl)) {
            return AjaxResult.error("Word文件URL不能为空");
        }

        try {
            // 下载URL到临时文件
            File tempWordFile = DocumentUtils.downloadUrlToTempFile(fileUrl, "word_to_pdf_", 
                    fileUrl.toLowerCase().endsWith(".docx") ? ".docx" : ".doc");
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_conversion" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 生成唯一的输出文件名
            String outputFileName = DocumentUtils.generateTempFileName("word_to_pdf_", ".pdf");
            String outputPdfPath = outputDir + File.separator + outputFileName;
            
            // 执行转换
            boolean success = DocumentUtils.convertWordToPdf(tempWordFile, outputPdfPath);
            
            if (success) {
                // 将本地文件路径转换为HTTP URL，包含完整域名
                String httpUrl = DocumentUtils.getHttpUrl(outputPdfPath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                
                // 返回HTTP URL
                AjaxResult result = AjaxResult.success("Word转PDF成功")
                        .put("url", httpUrl);
                return saveFileAndLog(getUserId(), result, "Word转PDF");
            } else {
                return AjaxResult.error("Word转PDF失败");
            }
        } catch (Exception e) {
            log.error("Word转PDF处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("Word转PDF处理失败：" + e.getMessage());
        }
    }

    /**
     * Word转图片 - 文件上传方式
     *
     * @param file Word文件
     * @return 转换结果
     */
    @Override
    public AjaxResult convertWordToImage(MultipartFile file) throws Exception {
        if (file == null) {
            return AjaxResult.error("Word文件不能为空");
        }

        // 校验文件类型
        String originalFilename = file.getOriginalFilename();
        if (!FileTypeUtils.isWord(originalFilename)) {
            return AjaxResult.error("仅支持DOC、DOCX格式文件");
        }

        try {
            // 创建临时文件
            File tempWordFile = DocumentUtils.saveTempFile(file, "word_to_image_", 
                    originalFilename.substring(originalFilename.lastIndexOf(".")));
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_conversion" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                    + File.separator + UUID.randomUUID().toString().substring(0, 8);
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 执行转换
            List<String> imagePaths = DocumentUtils.convertWordToImages(tempWordFile, outputDir);
            
            if (imagePaths != null && !imagePaths.isEmpty()) {
                // 将本地文件路径转换为HTTP URL
                List<String> imageUrls = new ArrayList<>();
                for (String imagePath : imagePaths) {
                    String httpUrl = DocumentUtils.getHttpUrl(imagePath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                    imageUrls.add(httpUrl);
                }
                
                // 返回图片URL列表
                AjaxResult result = AjaxResult.success("Word转图片成功")
                        .put("images", imageUrls);
                return saveFileAndLog(getUserId(), result, "Word转图片");
            } else {
                return AjaxResult.error("Word转图片失败");
            }
        } catch (Exception e) {
            log.error("Word转图片处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("Word转图片处理失败：" + e.getMessage());
        }
    }

    /**
     * Word转图片 - Base64编码方式
     *
     * @param fileBase64 Word文件的Base64编码
     * @return 转换结果
     */
    @Override
    public AjaxResult convertWordToImageByBase64(String fileBase64) throws Exception {
        if (StringUtils.isEmpty(fileBase64)) {
            return AjaxResult.error("Word文件Base64编码不能为空");
        }

        try {
            // 将Base64转换为临时文件
            File tempWordFile = DocumentUtils.saveTempFileFromBase64(fileBase64, "word_to_image_", ".docx");
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_conversion" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                    + File.separator + UUID.randomUUID().toString().substring(0, 8);
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 执行转换
            List<String> imagePaths = DocumentUtils.convertWordToImages(tempWordFile, outputDir);
            
            if (imagePaths != null && !imagePaths.isEmpty()) {
                // 将本地文件路径转换为HTTP URL
                List<String> imageUrls = new ArrayList<>();
                for (String imagePath : imagePaths) {
                    String httpUrl = DocumentUtils.getHttpUrl(imagePath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                    imageUrls.add(httpUrl);
                }
                
                // 返回图片URL列表
                AjaxResult result = AjaxResult.success("Word转图片成功")
                        .put("images", imageUrls);
                return saveFileAndLog(getUserId(), result, "Word转图片");
            } else {
                return AjaxResult.error("Word转图片失败");
            }
        } catch (Exception e) {
            log.error("Word转图片处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("Word转图片处理失败：" + e.getMessage());
        }
    }

    /**
     * Word转图片 - URL方式
     *
     * @param fileUrl Word文件的URL
     * @return 转换结果
     */
    @Override
    public AjaxResult convertWordToImageByUrl(String fileUrl) throws Exception {
        if (StringUtils.isEmpty(fileUrl)) {
            return AjaxResult.error("Word文件URL不能为空");
        }

        try {
            // 下载URL到临时文件
            File tempWordFile = DocumentUtils.downloadUrlToTempFile(fileUrl, "word_to_image_", 
                    fileUrl.toLowerCase().endsWith(".docx") ? ".docx" : ".doc");
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_conversion" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))
                    + File.separator + UUID.randomUUID().toString().substring(0, 8);
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 执行转换
            List<String> imagePaths = DocumentUtils.convertWordToImages(tempWordFile, outputDir);
            
            if (imagePaths != null && !imagePaths.isEmpty()) {
                // 将本地文件路径转换为HTTP URL
                List<String> imageUrls = new ArrayList<>();
                for (String imagePath : imagePaths) {
                    String httpUrl = DocumentUtils.getHttpUrl(imagePath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                    imageUrls.add(httpUrl);
                }
                
                // 返回图片URL列表
                AjaxResult result = AjaxResult.success("Word转图片成功")
                        .put("images", imageUrls);
                return saveFileAndLog(getUserId(), result, "Word转图片");
            } else {
                return AjaxResult.error("Word转图片失败");
            }
        } catch (Exception e) {
            log.error("Word转图片处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("Word转图片处理失败：" + e.getMessage());
        }
    }

    /**
     * 加密文档 - 文件上传方式
     *
     * @param file 文档文件
     * @param password 用户密码
     * @param ownerPassword 所有者密码
     * @return 加密结果
     */
    @Override
    public AjaxResult encryptDocument(MultipartFile file, String password, String ownerPassword) throws Exception {
        if (file == null) {
            return AjaxResult.error("文档文件不能为空");
        }

        // 校验文件类型
        String originalFilename = file.getOriginalFilename();
        if (!FileTypeUtils.isPdf(originalFilename) && !FileTypeUtils.isWord(originalFilename)) {
            return AjaxResult.error("仅支持PDF、DOC、DOCX格式文件加密");
        }

        try {
            // 获取文件后缀
            String fileSuffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            
            // 创建临时文件
            File tempFile = DocumentUtils.saveTempFile(file, "encrypt_doc_", fileSuffix);
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_encryption" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 生成唯一的输出文件名，根据文件类型设置正确的扩展名
            String outputExtension = FileTypeUtils.isPdf(originalFilename) ? ".pdf" : 
                    (originalFilename.toLowerCase().endsWith(".docx") ? ".docx" : ".doc");
            String outputFileName = DocumentUtils.generateTempFileName("encrypted_", outputExtension);
            String outputFilePath = outputDir + File.separator + outputFileName;
            
            // 执行加密
            boolean success = DocumentUtils.encryptDocument(tempFile, outputFilePath, password, ownerPassword);
            
            if (success) {
                // 将本地文件路径转换为HTTP URL，包含完整域名
                String httpUrl = DocumentUtils.getHttpUrl(outputFilePath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                
                // 返回HTTP URL
                AjaxResult result = AjaxResult.success("文档加密成功")
                        .put("url", httpUrl);
                return saveFileAndLog(getUserId(), result, "文档加密");
            } else {
                return AjaxResult.error("文档加密失败");
            }
        } catch (Exception e) {
            log.error("文档加密处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("文档加密处理失败：" + e.getMessage());
        }
    }

    /**
     * 加密文档 - Base64编码方式
     *
     * @param fileBase64 文档文件的Base64编码
     * @param password 用户密码
     * @param ownerPassword 所有者密码
     * @return 加密结果
     */
    @Override
    public AjaxResult encryptDocumentByBase64(String fileBase64, String password, String ownerPassword) throws Exception {
        if (StringUtils.isEmpty(fileBase64)) {
            return AjaxResult.error("文档文件Base64编码不能为空");
        }

        try {
            // 检测文件类型
            // 通过Base64头部字节判断文件类型
            byte[] fileBytes = Base64.getDecoder().decode(fileBase64);
            String fileType = detectFileType(fileBytes);
            
            String fileSuffix;
            if (fileType.equals("docx")) {
                fileSuffix = ".docx";
            } else if (fileType.equals("doc")) {
                fileSuffix = ".doc";
            } else {
                fileSuffix = ".pdf";
            }
            
            // 将Base64转换为临时文件
            File tempFile = DocumentUtils.saveTempFileFromBase64(fileBase64, "encrypt_doc_", fileSuffix);
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_encryption" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 生成唯一的输出文件名，使用与原文件相同的扩展名
            String outputFileName = DocumentUtils.generateTempFileName("encrypted_", fileSuffix);
            String outputFilePath = outputDir + File.separator + outputFileName;
            
            // 执行加密
            boolean success = DocumentUtils.encryptDocument(tempFile, outputFilePath, password, ownerPassword);
            
            if (success) {
                // 将本地文件路径转换为HTTP URL，包含完整域名
                String httpUrl = DocumentUtils.getHttpUrl(outputFilePath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                
                // 返回HTTP URL
                AjaxResult result = AjaxResult.success("文档加密成功")
                        .put("url", httpUrl);
                return saveFileAndLog(getUserId(), result, "文档加密");
            } else {
                return AjaxResult.error("文档加密失败");
            }
        } catch (Exception e) {
            log.error("文档加密处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("文档加密处理失败：" + e.getMessage());
        }
    }

    /**
     * 检测文件类型（通过字节头部特征）
     *
     * @param fileBytes 文件字节数组
     * @return 文件类型（docx, doc, pdf）
     */
    private String detectFileType(byte[] fileBytes) {
        if (fileBytes.length < 8) {
            return "pdf"; // 默认PDF
        }
        
        // DOCX文件特征：PK\003\004 (ZIP格式)
        if (fileBytes[0] == 0x50 && fileBytes[1] == 0x4B && fileBytes[2] == 0x03 && fileBytes[3] == 0x04) {
            return "docx";
        }
        
        // DOC文件特征：D0CF11E0
        if (fileBytes[0] == (byte)0xD0 && fileBytes[1] == (byte)0xCF && 
            fileBytes[2] == (byte)0x11 && fileBytes[3] == (byte)0xE0) {
            return "doc";
        }
        
        // PDF文件特征：%PDF (25 50 44 46)
        if (fileBytes[0] == 0x25 && fileBytes[1] == 0x50 && 
            fileBytes[2] == 0x44 && fileBytes[3] == 0x46) {
            return "pdf";
        }
        
        return "pdf"; // 默认PDF
    }

    /**
     * 加密文档 - URL方式
     *
     * @param fileUrl 文档文件的URL
     * @param password 用户密码
     * @param ownerPassword 所有者密码
     * @return 加密结果
     */
    @Override
    public AjaxResult encryptDocumentByUrl(String fileUrl, String password, String ownerPassword) throws Exception {
        if (StringUtils.isEmpty(fileUrl)) {
            return AjaxResult.error("文档文件URL不能为空");
        }

        try {
            // 根据URL后缀确定文件类型
            String suffix;
            if (fileUrl.toLowerCase().endsWith(".pdf")) {
                suffix = ".pdf";
            } else if (fileUrl.toLowerCase().endsWith(".docx")) {
                suffix = ".docx";
            } else if (fileUrl.toLowerCase().endsWith(".doc")) {
                suffix = ".doc";
            } else {
                return AjaxResult.error("仅支持PDF、DOC、DOCX格式文件加密");
            }
            
            // 下载URL到临时文件
            File tempFile = DocumentUtils.downloadUrlToTempFile(fileUrl, "encrypt_doc_", suffix);
            
            // 创建输出目录，使用系统配置的上传路径
            String outputDir = RuoYiConfig.getProfile() + File.separator + "document_encryption" 
                    + File.separator + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 确保目录存在
            File dir = new File(outputDir);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            
            // 生成唯一的输出文件名，使用与原文件相同的扩展名
            String outputFileName = DocumentUtils.generateTempFileName("encrypted_", suffix);
            String outputFilePath = outputDir + File.separator + outputFileName;
            
            // 执行加密
            boolean success = DocumentUtils.encryptDocument(tempFile, outputFilePath, password, ownerPassword);
            
            if (success) {
                // 将本地文件路径转换为HTTP URL，包含完整域名
                String httpUrl = DocumentUtils.getHttpUrl(outputFilePath, RuoYiConfig.getProfile(), Constants.RESOURCE_PREFIX, serverConfig.getUrl());
                
                // 返回HTTP URL
                AjaxResult result = AjaxResult.success("文档加密成功")
                        .put("url", httpUrl);
                return saveFileAndLog(getUserId(), result, "文档加密");
            } else {
                return AjaxResult.error("文档加密失败");
            }
        } catch (Exception e) {
            log.error("文档加密处理失败：{}", e.getMessage(), e);
            return AjaxResult.error("文档加密处理失败：" + e.getMessage());
        }
    }

    /**
     * 保存成功处理文件信息并记录日志
     * 
     * @param userId 用户ID
     * @param result 处理结果
     * @param operationType 操作类型
     * @return 处理结果
     */
    private AjaxResult saveFileAndLog(Long userId, AjaxResult result, String operationType) {
        if (result == null || !result.isSuccess()) {
            return result;
        }
        
        try {
            // 保存文件信息到数据库，如果成功会自动记录日志，或者标记为已记录
            boolean fileSaved = xhFileService.saveFileFromResult(userId, result, operationType);
            
            // 所有日志记录操作都已经在 xhFileService.saveFileFromResult 或 OperationLogServiceImpl 中添加了防重复机制
            // 这里不再重复记录，只是为了兼容旧代码保留了这段逻辑
            
            return result;
        } catch (Exception e) {
            log.error("保存文件信息或记录日志失败: {}", e.getMessage(), e);
            return result;
        }
    }

    /**
     * 获取当前登录用户ID
     */
    private Long getUserId() {
        try {
            return SecurityUtils.getUserId();
        } catch (Exception e) {
            log.warn("获取用户ID失败，使用默认值: {}", e.getMessage());
            return 1L; // 默认用户ID
        }
    }
} 